using System.Collections.Generic;
using Arcane.Source.Combat;
using Arcane.Source.Combat.SpellAction;
using Godot;
using Nett;

namespace Arcane.Source.Data;

public class SpellDB
{
    private readonly Dictionary<StringName, SpellProto> spells = [];
    public void Init(TextureDB textures, string path)
    {
        foreach (var (id, table) in LoadUtil.LoadTomlFiles(path))
        {
            var name = table.Get<string>("name");
            var proto = new SpellProto
            {
                name = name,
                desc = name + ".desc",
                icon = textures.Get(table.Get<string>("icon")),
                actions = table.TryGetValue("actions", out var actions) ? DeserializeActions((TomlTableArray)actions) : [],
            };
            spells.Add(id, proto);
        }
    }

    public SpellProto Get(StringName id) => spells.TryGetValue(id, out var proto) ? proto : null;

    private static ISpellAction[] DeserializeActions(TomlTableArray actions)
    {
        List<ISpellAction> ret = [];
        foreach (var action in actions.Items)
        {
            if (action.Count == 0) continue;
            var type = action.Get<string>("type");
            switch (type)
            {
                case "attack":
                    var dmgType = action.TryGetValue("damage_type", out var typeName) ? DamageTypeExt.Parse(typeName.Get<string>()) : DamageType.Common;
                    ret.Add(new Attack(action.Get<int>("target"), action.Get<float>("amount"), dmgType));
                    break;
                case "charge":
                    ret.Add(new Charge(action.Get<float>("amount")));
                    break;
                case "attach_effect":
                    var effect = action.Get<TomlTable>("effect");
                    ret.Add(new AttachEffect(action.Get<int>("target"), effect.Get<string>("type"), [.. Json.ParseString(effect.Get<string>("args")).AsGodotArray()]));
                    break;
                default:
                    break;
            }
        }
        return [.. ret];
    }
}